home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Games of Daze
/
Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso
/
x2ftp
/
msdos
/
progsrc
/
3d_2
/
3d_2a.cpp
< prev
next >
Wrap
C/C++ Source or Header
|
1994-12-18
|
8KB
|
406 lines
// 3D Rotation Program 3D_2.CPP
// adding edge class
// 18/12/94
#define version "1.09"
// sine angle lookup table added (floating point)
// transformation data read from data file
// calculates surface normals from shading
// support for OFF files via FILTER2 added
#include "3d_2a.h"
// prototypes
void read_absolute_coords(char name[], surface *s_ptr, vector *v_ptr);
void draw(surface *s_ptr, vector *e_ptr, int line_remove);
void hidden_face_remove(matrix m_ptr, surface *s_ptr, vector *v_ptr);
void image_clear(int x, int y);
void convert_vertex_eye(matrix matr, vector *v_ptr, vector *e_ptr);
void get_filename(char *file_name);
void fast_kbflush(void);
void grey_16_palette(void);
main(int argc, char *argv[])
{
int hidden_line_removal = true;
int redraw = false;
matrix view;
clock_t start, stop;
if (argc!=2)
{
cout << "\nRotates a 3D object.\n3D_2 [datafile._3d]\n";
exit(1);
}
char file_name[80];
strcpy(file_name, argv[1]);
get_filename(&file_name[0]); // get the file name
ifstream in(file_name);
// if cann't open file then exit
if (!in)
{
cout << "Cannot open file " << file_name;
exit(1);
}
in >> no_of_vertices;
in >> no_of_surfaces;
vector *vertex, *eye_vertex;
surface *surf;
vertex = new vector[no_of_vertices];
eye_vertex = new vector[no_of_vertices];
surf = new surface[no_of_surfaces];
if (!surf || !vertex || !eye_vertex)
{
cout << "Allocation error\n";
exit(1);
}
read_absolute_coords(file_name, surf, vertex);
// goto graphics mode
int driver = VGA;
int mode = VGAHI;
initgraph(&driver, &mode, "");
int errorcode;
errorcode = graphresult();
if (errorcode != grOk)
{
cout << "Graphics error: " << grapherrormsg(errorcode) << "\n";
exit(1);
}
setcolor(WHITE);
int x_max, y_max;
x_max = getmaxx();
y_max = getmaxy();
grey_16_palette();
// calculate transformation matrix
view.calculate();
// calculate normal vectors
for(int surfaceno=0; surfaceno<no_of_surfaces; surfaceno++)
{
surf[surfaceno].calculate_normal(vertex);
}
hidden_face_remove(view, surf, vertex);
convert_vertex_eye(view, vertex, eye_vertex);
draw(surf, eye_vertex, hidden_line_removal);
int ch;
do
{
ch = getch();
if (ch==0) ch = getch() + 256;
fast_kbflush();
redraw = false;
switch (ch)
{
case 328:
view.set_phi(5);
redraw = true;
break;
case 336: //
view.set_phi(-5);
redraw = true;
break;
case 333: // 'right' arrow key
view.set_theta(5);
redraw = true;
break;
case 331: // 'left' arrow key
view.set_theta(-5);
redraw = true;
break;
case 45: // '+' key
view.set_rho(20);
redraw = true;
break;
case 43: // '-' key
view.set_rho(-20);
redraw = true;
break;
case 104: // 'h' key
// if hidden line removal on then turn off, and vice-versa
hidden_line_removal = hidden_line_removal ? false : true;
redraw = true;
break;
default:
break;
}
if (redraw)
{
// remove old image
image_clear(x_max, y_max);
// draw new image
start = clock();
view.calculate();
if (hidden_line_removal) hidden_face_remove(view, surf, vertex);
convert_vertex_eye(view, vertex, eye_vertex);
draw(surf, eye_vertex, hidden_line_removal);
stop = clock();
}
} while (ch != 113); // 'q' key
// return back to dos
restorecrtmode();
cout << "\n3D Rotation program version " << version << "\n";
cout << "Compiled on " << __DATE__ << " at " << __TIME__ << "\n";
printf("The time was: %f\n", (stop - start) / CLK_TCK);
exit(0);
}
void draw(surface *s_ptr, vector *e_ptr, int line_remove)
{
float xe,ye,ze;
int xs,ys;
int q, p, *poly, num;
int screendist = 2000;
int surfaceno;
for(surfaceno=0; surfaceno<no_of_surfaces; surfaceno++)
{
// if visible draw surface or if hidden line removal off
if ((s_ptr[surfaceno].get_visible()) || (!line_remove))
{
num = s_ptr[surfaceno].get_no_of_verts();
p = (num*2)+2;
poly = new int[p];
if (!poly) exit(1);
int j;
for(j=0; j<s_ptr[surfaceno].get_no_of_verts(); j++)
{
q = s_ptr[surfaceno].get_vert(j);
xe = e_ptr[q].get_x();
ye = e_ptr[q].get_y();
ze = e_ptr[q].get_z();
xs = screendist * (xe / ze);
ys = screendist * (ye / ze);
if (!j)
{
poly[(num*2)] = xs + origin_x;
poly[(num*2)+1] = ys + origin_y;
//moveto (xs + origin_x, ys + origin_y);
}
poly[j*2] = xs + origin_x;
poly[(j*2)+1] = ys + origin_y;
}
if (!line_remove) drawpoly((p/2), poly);
else
{
setfillstyle(SOLID_FILL, s_ptr[surfaceno].get_shading());
fillpoly((p/2),poly);
}
delete [p] poly;
}
}
}
// initialise the arrays
void read_absolute_coords(char name[], surface *s_ptr, vector *v_ptr)
{
int no,x,y,z;
char ch;
ifstream in(name);
// if cann't open file then exit
if (!in)
{
exit(1);
}
cout << "Reading data file " << name << "\n";
int tmp_num;
in >> tmp_num; // find no. of vertices
in >> tmp_num; // find no. of surfaces
in >> tmp_num; // total no. of vertices & surfaces
for(int i=0; i<no_of_vertices; i++)
{
in >> x;
in >> y;
in >> z;
v_ptr[i].assign(x,y,z);
}
int vertice;
int vert[9];
for(i=0; i<no_of_surfaces; i++)
{
in >> vertice;
if (vertice > 8)
{
cout << "\nAt present can only a max. of 8 vertices to a surface\n";
exit(1);
}
s_ptr[i].init_vert(vertice);
for(int j=0; j<vertice; j++)
{
in >> vert[j];
if (vert[j] < 0)
{
cout << "\nVertex number is -ve\n";
exit(1);
}
}
s_ptr[i].set_vert(vert);
}
in.close();
}
void hidden_face_remove(matrix m_ptr, surface *s_ptr, vector *v_ptr)
{
vector view;
{
float sin_phi;
int theta, phi, rho;
theta = m_ptr.get_theta();
phi = m_ptr.get_phi();
rho = m_ptr.get_rho();
sin_phi = f_sin(phi);
long v1,v2,v3;
v1 = rho * sin_phi * f_cos(theta);
v2 = rho * sin_phi * f_sin(theta);
v3 = rho * f_cos(phi);
view.assign(v1,v2,v3);
}
int surfaceno, t0;
vector los;
for (surfaceno=0; surfaceno<no_of_surfaces; surfaceno++)
{
// calculate line of sight vectors
t0 = s_ptr[surfaceno].get_vert(0);
los = view - v_ptr[t0];
// is it visible ?
//s_ptr[surfaceno].calculate_visibility(los);
s_ptr[surfaceno].calculate_shading(los);
}
}
// clears the image
void image_clear(int x, int y)
{
int box[] = {0,0, 0,y+1, x,y+1, x,0};
int color;
color = getcolor();
setcolor(BLACK);
setfillstyle(SOLID_FILL, BLACK);
fillpoly(4,box);
setcolor(color);
}
// converts the world co-ordinates into eye co-ordinates
void convert_vertex_eye(matrix matr, vector *v_ptr, vector *e_ptr)
{
vector temp;
for(int vertexno=0; vertexno<no_of_vertices; vertexno++)
{
temp.assign(v_ptr[vertexno]);
// multiply vector with matrix
temp = temp * (matr);
e_ptr[vertexno].assign(temp);
}
}
// set the 16 colour palette to 15 shades of grey
void grey_16_palette(void)
{
register int j;
struct palettetype pal;
// load the colour palette with the 15 shades of grey
getpalette (&pal);
for (j=0; j<pal.size; j++)
setrgbpalette (pal.colors[j], j*4, j*4, j*4);
}
void fast_kbflush(void)
{
*((unsigned far *)MK_FP(0x40, 0x1a)) = *((unsigned far *)MK_FP(0x40, 0x1c));
}
// append a ._3d to the file name
void get_filename(char *file_name)
{
char drive[3];
char dir[66];
char fname[9];
char file[9];
char ext[5];
int flag;
flag = fnsplit(file_name, drive, dir, fname, ext);
if (flag & WILDCARDS)
{
cout << "Wildcard found in file name.\n";
exit(1);
}
if (!(flag & FILENAME))
{
cout << "A file name is required!\n";
exit(1);
}
getcwd(file_name,MAXPATH); // get current directory
strcat(file_name,"\\"); // append a trailing \
fnsplit(file_name,drive,dir,file,ext);
strupr(fname);
strcpy(file,fname);
strcpy(ext,"._3D");
// read file from the current dir
fnmerge(file_name,drive,dir,file,ext);
}